/**
 * 权限码守卫
 * 使用缓存机制减少数据库查询
 */

import { CanActivate, ExecutionContext, Injectable, ForbiddenException, Logger } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { PermissionCacheService } from '../services/permission-cache.service';
import { PERMISSIONS_KEY } from '../decorators/permission.decorator';

@Injectable()
export class PermissionCodeGuard implements CanActivate {
  private readonly logger = new Logger(PermissionCodeGuard.name);

  constructor(
    private reflector: Reflector,
    private permissionCacheService: PermissionCacheService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const { user } = request;

    if (!user || !user.userId) {
      this.logger.warn('用户未认证');
      throw new ForbiddenException('用户未认证');
    }

    // 获取装饰器中要求的权限代码
    const requiredPermissions = this.reflector.get<string[]>(PERMISSIONS_KEY, context.getHandler());
    
    // 如果没有要求权限，则放行
    if (!requiredPermissions || requiredPermissions.length === 0) {
      return true;
    }

    // 检查用户是否是超级管理员，超级管理员拥有所有权限
    const roleCodes = user.roleCodes || user.roles || [];
    if (Array.isArray(roleCodes) && roleCodes.includes('SUPER_ADMIN')) {
      this.logger.debug(`用户 ${user.username || user.userId} 是超级管理员，权限检查通过`);
      return true;
    }

    // 从请求头中提取 token，用于调用 eorder-server
    const authHeader = request.headers.authorization;
    const requestToken = authHeader ? authHeader.replace('Bearer ', '') : undefined;

    // 使用缓存服务获取用户权限代码（减少数据库查询）
    try {
      const userPermissionCodes = await this.permissionCacheService.getUserPermissions(
        user.userId,
        Array.isArray(roleCodes) ? roleCodes : [],
        requestToken
      );

      // 检查用户是否拥有任一所需权限
      const hasPermission = requiredPermissions.some(permission => 
        userPermissionCodes.includes(permission)
      );

      if (!hasPermission) {
        this.logger.warn(`用户 ${user.username || user.userId} 没有所需权限: ${requiredPermissions.join(', ')}`);
        throw new ForbiddenException('权限不足，请联系管理员申请权限');
      }

      this.logger.debug(`用户 ${user.username || user.userId} 权限检查通过: ${requiredPermissions.join(', ')}`);
      return true;
    } catch (error) {
      if (error instanceof ForbiddenException) {
        throw error;
      }
      this.logger.error(`权限检查失败: ${error.message}`);
      throw new ForbiddenException('权限检查失败');
    }
  }
}

